import React, { Component } from "react";
import PropTypes from "prop-types";
import { connect } from "dva";
import { Table } from "antd";
import { openNotificationWithIcon } from "utils/comm";
import _ from "lodash";
import styles from "./index.less";

const noop = () => {};

const SORT_MAP = {
  ascend: "asc",
  descend: "desc",
};

class TableWrapper extends Component {
  openNotificationWithIcon = openNotificationWithIcon.bind(this);

  state = {
    loading: false,
    dataSource: [],
    total: 0,
    pageSize: 10,
    pageNum: 1,
    filters: {},
    sorter: {},
  };

  static propTypes = {
    api: PropTypes.string.isRequired, // 请求的接口地址
    columns: PropTypes.array, // 列
    query: PropTypes.object, // 请求时额外的查询参数
    selectedRows: PropTypes.array, // 选中的keys
    rowSelection: PropTypes.object, // 表格选择
    onRef: PropTypes.func, // 绑定表格的 ref
    beforeFetch: PropTypes.func, // 在提交搜索之前，对请求数据进行处理，例如修改字段名
    rowKey: PropTypes.string, // 表格的key index，多选时会返回这个字段
    onRow: PropTypes.func,
    afterTableChange: PropTypes.func, // 表格过滤条件改变之后的回调
  };

  static defaultProps = {
    columns: [],
    query: {},
    selectedRows: [],
    rowSelection: null,
    onRef: noop,
    beforeFetch: (val) => val,
    rowKey: "id",
    afterTableChange: null,
    onRow: () => ({}),
  };

  constructor(props) {
    super(props);
    const { onRef } = this.props;
    if (onRef !== noop) {
      onRef(this);
    }
  }

  componentDidMount() {
    this.fetch();
  }

  componentDidUpdate(prevProps) {
    const { query: pQuery } = this.props;
    const { query } = prevProps;
    if (!_.isEqual(query, pQuery)) {
      this.fetch({ pageNum: 1 });
    }
  }

  componentWillUnmount() {
    this.setState = () => {};
  }

  fetch = (updateState = {}) => {
    this.setState(
      {
        loading: true,
        ...updateState,
      },
      () => {
        const { dispatch, api, query, beforeFetch } = this.props;
        const { filters, sorter, pageSize, pageNum } = this.state;

        let entity = { query, sorter, filters };

        if (beforeFetch instanceof Function) {
          const newEntity = beforeFetch(entity);
          if (newEntity) entity = newEntity;
        }
        dispatch({
          type: "tableModel/fetch",
          payload: {
            api,
            pageSize,
            pageNum,
            query: {
              ...entity.query,
              ...entity.sorter,
              ...entity.filters,
            },
          },
        })
          .then((resp) => {
            if (resp) {
              if (resp.errCode === 0) {
                const {
                  datas: list = [],
                  pageNum: _pageNum,
                  totalCount,
                } = resp;
                // const reOrderData = list;
                if (_pageNum > 1 && list.length === 0) {
                  const newState = { pageNum: _pageNum - 1 };
                  this.setState(newState, () => {
                    this.fetch();
                  });
                } else {
                  this.setState({
                    dataSource: Array.isArray(list) ? list : [],
                    total: totalCount,
                    pageNum: _pageNum,
                  });
                }
              } else {
                this.openNotificationWithIcon(
                  "error",
                  "",
                  resp.errortext || "获取数据失败",
                );
              }
            }
          })
          .finally(() => {
            this.setState({ loading: false });
          });
      },
    );
  };

  handleTableChange = ({ current: pageNum, pageSize }, filters, sorter) => {
    const newState = Object.create(null);
    const { afterTableChange } = this.props;

    // 处理排序相关
    if (!_.isEmpty(sorter)) {
      const { column: { sorterKey } = {}, order, field } = sorter;
      const sortField = sorterKey || field;
      const orderType = SORT_MAP[order] || "";
      if (orderType) {
        newState.sorter = {
          order: orderType,
          sort: sortField,
        };
      } else {
        newState.sorter = {};
      }
    }

    // 处理过滤相关
    if (!_.isEmpty(filters)) {
      newState.filters = filters;
    }

    // 处理分页相关
    const { pageSize: oldPsize } = this.state;
    newState.pageNum = oldPsize !== pageSize ? 1 : pageNum;
    newState.pageSize = pageSize;

    this.setState(newState, () => {
      if (afterTableChange) {
        afterTableChange(newState);
      }
      this.fetch();
    });
  };

  rowClassName = (record) => {
    const { selectedRows } = this.props;
    if (!selectedRows || selectedRows.length <= 0) return;
    for (let i = 0; i < selectedRows.length; i += 1) {
      if (record.privId && selectedRows[i] === record.privId) {
        // 点击行的样式
        return "ant-table-row-selected";
      }
    }
    return "";
  };

  /**
   * 重新生成序号
   */
  generateOrderNum = (list, totalCount, sorter) => {
    if (!Array.isArray(list)) {
      return [];
    }
    const { pageNum, pageSize } = this.state;
    const { length } = list;
    const { order } = sorter;
    const howLong = this.getHowLong(totalCount);
    for (let i = 0; i < length; i += 1) {
      const item = list[i];
      let generatedOrderNum;
      if (order === "desc") {
        generatedOrderNum = totalCount - pageSize * (pageNum - 1) - i;
      } else {
        generatedOrderNum = pageSize * (pageNum - 1) + i + 1;
      }
      item.generatedOrderNum = generatedOrderNum;
      item.maxOrderLong = howLong; // 最大序号的位数，用于位数少时补0
    }
    return list;
  };

  /**
   * 获取一个数字的位数
   */
  getHowLong = (num) => {
    if (!num) {
      return 0;
    }
    return `${num}`.length;
  };

  render() {
    const { loading, dataSource, total, pageSize, pageNum } = this.state;
    const { columns, rowSelection, rowKey, onRow } = this.props;
    return (
      <Table
        className={styles.root}
        loading={loading}
        columns={columns}
        rowKey={(r) => r[rowKey]}
        rowSelection={rowSelection}
        dataSource={dataSource}
        rowClassName={this.rowClassName} // 权限选中样式特殊处理
        pagination={{
          current: pageNum,
          pageSize,
          total,
          showSizeChanger: true,
          showQuickJumper: true,
          pageSizeOptions: ["10", "20", "30", "40"],
        }}
        onChange={this.handleTableChange}
        onRow={onRow}
      />
    );
  }
}

export default connect()(TableWrapper);
